// server
#include "server_command.h"
#include "tcp.h"
#define CONNMAX 1024

int main(int argc, char *argv[]) {
    // ./server ip port
    ARG_CHECK(argc, 3);

    // 初始化被动套接字
    int listenfd = tcpInit(argv[1], atoi(argv[2]));

    // 创建epoll实例
    int epfd = epoll_create1(0);
    ERROR_CHECK(epfd, -1, "epoll_create1");

    // 将listen加入监听
    epollAddReadEvent(epfd, listenfd);

    while (1) {
        // 就绪文件描述符链表
        struct epoll_event *events = (struct epoll_event *)calloc(CONNMAX, sizeof(struct epoll_event));
        int nready = epoll_wait(epfd, events, CONNMAX, -1);
        if (nready == -1 && errno == EINTR) {
            continue;
        } else if (nready == -1) {
            perror("epoll_wait");
        } else if (nready > 0) {   // 存在就绪事件时
            for (int i = 0; i < nready; i++) {
                int fd = events[i].data.fd;
                // 有新连接时
                if (fd == listenfd) {
                    int peerfd = accept(listenfd, NULL, NULL);
                    ERROR_CHECK(peerfd,-1, "accept");
                    epollAddReadEvent(epfd, peerfd);

                    // 打印调试信息
                    printf("新连接成立\n");
                } else { // 旧连接有数据时
                    // 接受命令参数
                    char buf[100] = {0};
                    int len = recv(fd, buf, 100, 0);
                    if (len == -1 && errno == EINTR) {
                        continue;
                    } else if (len == -1) {
                        perror("reve");
                        continue;
                    } else if (len == 0) {
                        // 连接断开
                        // 删除监听
                        epollDelEvent(epfd, fd);
                        close(fd);
                        // 打印调试信息
                        printf("有连接断开\n");
                    } else {
                        // 接收到命令，执行对应接口函数
                        handle_server_cmd(buf, fd);
                    }
                }
            }
        }
    }

    // 关闭文件描述符
    close(epfd);
    close(listenfd);

    return 0;
}
